import CustomEvent = WechatMiniprogram.CustomEvent;
import {page, pageFunc} from "../common/PageBuilder";
import {ItemDetailPage} from "../common/pages/ItemDetailPage";
import {Certification, EducationNames, Identification, LongTimeTime} from "../../modules/userModule/data/User";
import {UserPage} from "../common/partPages/UserPage";
import {PickerPage} from "../common/partPages/PickerPage";
import {DatePicker} from "../common/partPages/DatePickerPage";
import {alertMgr, handleError} from "../../modules/coreModule/managers/AlertManager";
import {userMgr, waitForLogin} from "../../modules/userModule/managers/UserManager";
import {CloudFileUtils, MediaFile} from "../../utils/CloudFileUtils";
import {BasePageData} from "../common/core/BasePage";
import {field} from "../../modules/coreModule/data/DataLoader";
import {TemplateIds} from "../../modules/messageModule/MessageCommon";
import {waitForDataLoad} from "../../modules/coreModule/managers/DataManager";
import {Locations} from "../../utils/Locations";
import {DateUtils} from "../../utils/DateUtils";

// import tencentcloud from "tencentcloud-sdk-nodejs-sms";

const UploadName = "ident";
const UploadPath = "ident";
const MinDateTime = new Date(2000, 0, 1).getTime();
const MaxDateTime = new Date(2050, 0, 1).getTime();

// // 短信用到的
// const smsClient = tencentcloud.sms.v20210111.Client
// /* 实例化要请求产品(以sms为例)的client对象 */
// const client = new smsClient({
// 	credential: {
// 		secretId: "",  //预留，未改
// 		secretKey: "",  //预留，未改
// 	},
// 	region: "ap-guangzhou",  //预留，未改
// 	profile: {
// 		signMethod: "HmacSHA256",
// 		httpProfile: {
// 			reqMethod: "POST",
// 			reqTimeout: 30,
// 			endpoint: "sms.tencentcloudapi.com"
// 		},
// 	},
// })
// const params = {
// 	SmsSdkAppId: "1400610776",
// 	SignName: "广州艾瑟萌",
// 	TemplateId: "1244748",
// 	/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
// 	TemplateParamSet: ["1234"],
//
// 	PhoneNumberSet: ["+8613026883156"],
// 	/* 用户的 session 内容（无需要可忽略）: 可以携带用户侧 ID 等上下文信息，server 会原样返回 */
// 	SessionContext: "",
// 	/* 短信码号扩展号（无需要可忽略）: 默认未开通，如需开通请联系 [腾讯云短信小助手] */
// 	ExtendCode: "",
// 	/* 国际/港澳台短信 senderid（无需要可忽略）: 国内短信填空，默认未开通，如需开通请联系 [腾讯云短信小助手] */
// 	SenderId: "",
// }

class Data extends BasePageData {
	@field(Identification)
	item: Identification;

	// 身份证图片
	@field([Object])
	cardPictures: MediaFile[] = [];
	// 手持身份证图片
	@field(Object)
	cardAvatar: MediaFile;

	@field
	isLongTime: boolean = false; // 是否长期

	@field
	eduIdx: number = 0;

	@field
	minDate: number = MinDateTime;
	@field
	maxDate: number = MaxDateTime;
	@field
	endDate: number = Date.now();
	@field
	readonly: boolean = false;

	@field([Boolean])
	showProtocols: [boolean, boolean] = [false, false];
	@field(Boolean)
	isAgree: boolean = false;

}

class Param {
	identification: Identification
}

@page("idenAuth", "实名认证")
export class IdenAuthPage extends ItemDetailPage<Data, Identification, Param> {

	public data = new Data();

	/**
	 * 部分页
	 */
	public userPage: UserPage = new UserPage();
	public pickerPage: PickerPage = new PickerPage();
	public datePickerPage: DatePicker = new DatePicker();

	/**
	 * 初始化
	 */
	onLoad(e) {
		super.onLoad(e);
		this.loadData().then();
		// this.loadData().then();
	}
	/**
	 * 数据加载完成回调
	 */
	@waitForLogin
	@waitForDataLoad
	private loadData() {
		let item = new Identification();
		item.inviteCode = userMgr().savedInviteCode;

		let readonly = false;
		if (this.params?.identification){
			item = this.params.identification;
			readonly = true;
		}
		return this.setData({
			item, readonly
		})
	}
	// TODO: 添加各个字段的输入交互

	// region 输入字段交互

	@pageFunc
	public onPicture1Choose(e: CustomEvent) {
		if (this.data.readonly) return;
		const cardPictures = this.data.cardPictures;
		cardPictures[0] = e.detail.file;
		this.setData({cardPictures})
	}

	@pageFunc
	public onPicture2Choose(e: CustomEvent) {
		if (this.data.readonly) return;
		const cardPictures = this.data.cardPictures;
		cardPictures[1] = e.detail.file;
		this.setData({cardPictures})
	}

	@pageFunc
	public onCardAvatarChoose(e: CustomEvent) {
		if (this.data.readonly) return;
		this.setData({cardAvatar: e.detail.file})
	}

	@pageFunc
	public onNameChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({name: e.detail}).then();
	}

	@pageFunc
	public onGenderChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({gender: Number(e.detail)}).then();
	}

	@pageFunc
	public async onBirthTap(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		const maxDate = Date.now() - 18 * 365 * DateUtils.Day;
		const date = await this.datePickerPage.startPicker(
			"选择出生日期", maxDate, 0, maxDate);

		await this.setItemData({birth: date})
	}

	@pageFunc
	public async onLocationTap() {
		if (this.data.readonly) return;
		const locIdxs = await this.pickerPage.startPicker(
			"选择地点", Locations);
		console.log(locIdxs);
		if (!locIdxs) return;

		const province = Locations[locIdxs[0]];
		const city = province.sub[locIdxs[1]];
		const region = city.sub?.[locIdxs[2]];

		await this.setItemData({
			location: `${province.name} ${city.name} ${region?.name || ""}`
		})
	}

	@pageFunc
	public onAddressChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({address: e.detail}).then();
	}

	@pageFunc
	public onJobChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({job: e.detail}).then();
	}

	@pageFunc
	public onSpecialtyChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({specialty: e.detail}).then();
	}

	@pageFunc
	public onMirityChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({gender: Number(e.detail)}).then();
	}

	private get educationTexts() {
		return EducationNames.map(name => ({name}));
	}

	/**
	 * 角色点击回调
	 */
	@pageFunc
	public async onEducationTap() {
		if (this.data.readonly) return;
		const res = (await this.pickerPage.startPicker(
			"选择学历", this.educationTexts, this.data.eduIdx));
		if (res == null) return;

		await this.setItemData({education: res[0]})
	}

	@pageFunc
	public onVeteranChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({isVeteran: e.detail == "1"}).then();
	}

	@pageFunc
	public onCardNoChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({cardNo: e.detail}).then();
	}

	@pageFunc
	public onBankCardChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({bankCard: e.detail}).then();
	}

	@pageFunc
	public onAlipayInput(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({alipay: e.detail}).then();
	}

	@pageFunc
	public onInviteCodeChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setItemData({inviteCode: e.detail}).then();
	}

	@pageFunc
	public onChangePhone(e: CustomEvent<any>){
		if (this.data.readonly) return;
		this.setItemData({phone: e.detail}).then();
	}

	@pageFunc
	public sendVerificationCode(e) {
		// client.SendSms(params, function (err, response) {
		// 	// 请求异常返回，打印异常信息
		// 	if (err) {
		// 		console.log(err)
		// 		return
		// 	}
		// 	// 请求正常返回，打印response对象
		// 	console.log(response)
		// }).then();
	}
	@pageFunc
	public async getPhoneNumber(e) {
		if (this.data.readonly) return;
		if (!e.detail.code) return;
		// getPhone函数返回值
		const phone = await userMgr().getPhone(e.detail.code)
		await this.setItemData({ phone });

	}

	@pageFunc
	public onLongTimeChange(e: CustomEvent<any>) {
		if (this.data.readonly) return;
		this.setIsLongTime(e.detail == "1")
	}

	@pageFunc
	public async onStartTimeTap() {
		if (this.data.readonly) return;
		const date = await this.datePickerPage.startPicker("选择开始时间",
			this.item.startTime, this.data.minDate, Date.now());

		await this.setData({
			endDate: Math.max(this.data.endDate, date)
		});
		await this.setItemData({
			startTime: date,
			endTime: Math.max(this.item.endTime, date)
		})
	}

	@pageFunc
	public async onEndTimeTap() {
		if (this.data.readonly) return;
		if (this.data.isLongTime) return;
		const date = await this.datePickerPage.startPicker("选择过期时间",
			this.data.endDate, this.item.startTime, this.data.maxDate);

		await this.setData({endDate: date})
		await this.setItemData({endTime: date})
	}

	/**
	 * 设置是否长期
	 * @param val
	 */
	public setIsLongTime(val: boolean) {
		if (this.data.readonly) return;
		this.setData({isLongTime: val})
		this.setItemData({
			endTime: val ? LongTimeTime : this.data.endDate
		}).then();
	}

	/**
	 * 提交
	 */
	@pageFunc
	@handleError
	public submit() {
		if (this.data.readonly) return;
		this.check();
		wx.requestSubscribeMessage({
			tmplIds: [TemplateIds["审核通知"]],
			success: this.doSubmit.bind(this)
		})
	}
	private async doSubmit() {
		await this.uploadPictures();
		await userMgr().authIdent(this.item);
		if (await alertMgr().showAlert("信息已提交!"))
			this.back();
	}

	/**
	 * 校验格式
	 */
	private check() {
		if (!this.data.isAgree) throw "请同意服务协议和隐私政策";
		if (!this.data.cardPictures[0]) throw "请上传身份证人像面";
		if (!this.data.cardPictures[1]) throw "请上传身份证国徽面";
		if (this.data.item.isVeteran && !this.data.cardAvatar)
			throw "请上传手持退伍军人证照片";
		if (!this.item.name) throw "请输入名字";
		if (!this.item.cardNo) throw "请输入身份证号码";
		// if (!this.item.alipay) throw "请填写支付宝账号";
		if (!IdenAuthPage.checkCardNo(this.item.cardNo))
			throw "请输入有效身份证号码";
		// if (!this.item.bankCard) throw "请输入银行卡号";
		// if (!IdenAuthPage.checkBankCard(this.item.bankCard))
		// 	throw "请输入有效银行卡号";
		// if (this.item.bankCard && !IdenAuthPage.checkBankCard(this.item.bankCard))
		// 	throw "请输入有效银行卡号";
		if (!this.item.startTime || !this.item.endTime)
			throw "请填写身份证有效期";
		if (this.item.startTime > this.item.endTime)
			throw "开始时间不能大于结束时间";
	}

	/**
	 * 上传图片
	 */
	private async uploadPictures() {
		let tmpFiles = this.data.cardPictures;
		let files = tmpFiles.map(f => CloudFileUtils.mediaFile2File(UploadName, f));
		let fileIds = await CloudFileUtils.uploadFiles(files, UploadPath);
		await this.setItemData({images: fileIds});

		tmpFiles = [this.data.cardAvatar];
		files = tmpFiles.map(f => CloudFileUtils.mediaFile2File(UploadName, f));
		fileIds = await CloudFileUtils.uploadFiles(files, UploadPath);
		await this.setItemData({cardAvatar: fileIds[0]});
	}

	@pageFunc
	public closeProto() {
		this.setData({ showProtocols: [false, false] })
	}
	@pageFunc
	public openProto1() {
		this.setData({ "showProtocols[0]": true })
	}
	@pageFunc
	public openProto2() {
		this.setData({ "showProtocols[1]": true })
	}
	@pageFunc
	public onAgree() {
		this.setData({ isAgree: !this.data.isAgree })
	}

	// region 身份证号码验证

	/**
	 * 18位二代身份证号码的正则表达式
	 */
	private static REGEX_ID_NO_18: RegExp = /^\d{6}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/

	/**
	 * 15位一代身份证号码的正则表达式
	 */
	private static REGEX_ID_NO_15: RegExp = /^\d{6}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$/

	/**
	 * 校验身份证号码
	 * @param cardNo 身份证号码
	 * @return true - 校验通过<br>
	 *         false - 校验不通过
	 */
	private static checkCardNo(cardNo: string): boolean {
		return (cardNo.length == 18 //检测二代身份证份证是否有18位
				&& IdenAuthPage.REGEX_ID_NO_18.test(cardNo)  // 匹配身份证号码的正则表达式
				&& this.validateCheckNumber(cardNo)) // 校验身份证号码的验证码
			|| (cardNo.length == 15 //检测一代身份证是否有15位
				&& IdenAuthPage.REGEX_ID_NO_15.test(cardNo)); // 检测一代身份证是否匹配正则表达式
	}

	/**
	 * 校验18位身份证的校验码
	 */
	private static validateCheckNumber(cardNo18: string): boolean {
		let W: number[] = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
		let cardNo18Array: string[] = cardNo18.split("");
		let sum: number = 0;
		for (let i = 0; i < W.length; i++) {
			sum += Number(cardNo18Array[i]) * W[i];
		}

		// 校验位是X则表示10 该位的加权因子为1
		if (cardNo18Array[17] == 'X' || cardNo18Array[17] == 'x')
			sum += 10;
		else
			sum += Number(cardNo18Array[17]);

		//如果除11模1，则校验通过
		return sum % 11 == 1;
	}

	// endregion

	// region 银行卡号验证

	private static checkBankCard(bankCard: string): boolean {
		return bankCard.length >= 15;

		// let bankCardArray: string[] = bankCard.split("");
		// let sum: number = 0;
		// let n: number = bankCard.length;
		//
		// for (let i = n; i >= 1; i--) {
		// 	let a: number = Number(bankCardArray[n - i]);
		// 	if (i % 2 == 0) a *= 2;
		//
		// 	sum = sum + a / 10 + a % 10;
		// }
		// return sum % 10 == 0;
	}

	// endregion

}
